﻿using System.ComponentModel;
using System.Globalization;
using System.Runtime.InteropServices;

namespace CardPlay.Model.Primitives
{
    [StructLayout(LayoutKind.Sequential)]
    public struct Point
    {
        private int _x;
        private int _y;

        public static readonly Point Empty;

        static Point()
        {
            Empty = new Point();
        }

        public Point(int x, int y)
        {
            _x = x;
            _y = y;
        }

        public Point(Size size)
        {
            _x = size.Width;
            _y = size.Height;
        }

        public Point(int dw)
        {
            _x = (short)LOWORD(dw);
            _y = (short)HIWORD(dw);
        }

#if !WINDOWS_PHONE
        [Browsable(false)]
#endif
        public bool IsEmpty
        {
            get
            {
                return (_x == 0) && (_y == 0);
            }
        }

        public int X
        {
            get { return _x; }
            set { _x = value; }
        }

        public int Y
        {
            get { return _y; }
            set { _y = value; }
        }

        public static explicit operator Size(Point p)
        {
            return new Size(p.X, p.Y);
        }

        public static Point operator +(Point pt, Size sz)
        {
            return Add(pt, sz);
        }

        public static Point operator -(Point pt, Size sz)
        {
            return Subtract(pt, sz);
        }

        public static bool operator ==(Point left, Point right)
        {
            return ((left.X == right.X) && (left.Y == right.Y));
        }

        public static bool operator !=(Point left, Point right)
        {
            return !(left == right);
        }

        public static Point Add(Point pt, Size sz)
        {
            return new Point(pt.X + sz.Width, pt.Y + sz.Height);
        }

        public static Point Subtract(Point pt, Size sz)
        {
            return new Point(pt.X - sz.Width, pt.Y - sz.Height);
        }

        public override bool Equals(object obj)
        {
            if (!(obj is Point))
            {
                return false;
            }
            var point = (Point)obj;
            return ((point.X == X) && (point.Y == Y));
        }

        public override int GetHashCode()
        {
            return (_x ^ _y);
        }

        public void Offset(int dx, int dy)
        {
            X += dx;
            Y += dy;
        }

        public void Offset(Point p)
        {
            Offset(p.X, p.Y);
        }

        public override string ToString()
        {
            return ("{X=" + X.ToString(CultureInfo.CurrentCulture) + ",Y=" + Y.ToString(CultureInfo.CurrentCulture) + "}");
        }

        private static int HIWORD(int n)
        {
            return ((n >> 0x10) & 0xffff);
        }

        private static int LOWORD(int n)
        {
            return (n & 0xffff);
        }
    }
}